{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5]\n"
     ]
    }
   ],
   "source": [
    "# 列表推导式\n",
    "nums = [number for number in range(1, 6)]\n",
    "print(nums)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'r': 1, 's': 1, 't': 2, 'e': 2, 'l': 1}\n"
     ]
    }
   ],
   "source": [
    "# 字典推导式\n",
    "word = 'letters'\n",
    "letters = {letter: word.count(letter) for letter in word}\n",
    "print(letters)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{1, 4}\n"
     ]
    }
   ],
   "source": [
    "# 集合推导式\n",
    "a_set = {number for number in range(1, 6) if number % 3 == 1}\n",
    "print(a_set)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Monday : drink  coffee  - eat  banana  - enjoy  tiramisu\n",
      "Tuesday : drink  tea  - eat  orange  - enjoy  ice cream\n",
      "Wednesday : drink  beer  - eat  peach  - enjoy  pie\n"
     ]
    }
   ],
   "source": [
    "# zip()并行迭代\n",
    "days = ['Monday', 'Tuesday', 'Wednesday']\n",
    "fruits = ['banana', 'orange', 'peach']\n",
    "drinks = ['coffee', 'tea', 'beer']\n",
    "desserts = ['tiramisu', 'ice cream', 'pie', 'pudding']\n",
    "for day, fruit, drink, dessert in zip(days, fruits, drinks, desserts):\n",
    "    print(day, \": drink \", drink, \" - eat \", fruit, \" - enjoy \", dessert)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Harry', 'Henry', 'Barkley']\n",
      "Harry,Henry,Barkley\n"
     ]
    }
   ],
   "source": [
    "# split()与join()\n",
    "friends = \"Harry,Henry,Barkley\"\n",
    "friends_list = friends.split(',')\n",
    "print(friends_list)\n",
    "joined_str = ','.join(friends_list)\n",
    "print(joined_str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'dessert': 'cake', 'entree': 'chicken', 'wine': 'chardonnay'}\n",
      "{'dessert': 'bagel', 'entree': 'beef', 'wine': 'bordeaux'}\n"
     ]
    }
   ],
   "source": [
    "# 函数\n",
    "# 位置参数，如：\n",
    "def menu(wine, entree, dessert):\n",
    "    return {'wine': wine, 'entree': entree, 'dessert': dessert}\n",
    "print(menu('chardonnay', 'chicken', 'cake'))\n",
    "\n",
    "# 关键字参数，如：\n",
    "print(menu(entree='beef', dessert='bagel', wine='bordeaux'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Positional argument tuple:  (3, 2, 'wait!', 2, 'uh...')\n",
      "Need this one: cap\n",
      "Need this one too: 2\n",
      "All the rest: ('gloves', 'banana', 6)\n"
     ]
    }
   ],
   "source": [
    "# 函数\n",
    "# # args, 使用*号收集\n",
    "def print_args(*args):\n",
    "    print('Positional argument tuple: ', args)\n",
    "\n",
    "print_args(3, 2, 'wait!', 2, 'uh...')\n",
    "\n",
    "def print_more(required1, required2, *args):\n",
    "    print('Need this one:', required1)\n",
    "    print('Need this one too:', required2)\n",
    "    print('All the rest:', args)\n",
    "\n",
    "print_more('cap', 2, 'gloves', 'banana', 2*3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Keyword arguments:  {'wine': 'merlot', 'entree': 'mutton', 'dessert': 'macaroon'}\n"
     ]
    }
   ],
   "source": [
    "# 函数\n",
    "# # kwargs, 使用**号收集\n",
    "def print_kwargs(**kwargs):\n",
    "    print('Keyword arguments: ', kwargs)\n",
    "    \n",
    "print_kwargs(wine='merlot', entree='mutton', dessert='macaroon')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running function:  add_ints\n",
      "Positional arguments:  (3, 5)\n",
      "Keyword arguments:  {}\n",
      "Result:  8\n",
      "Running function:  add_ints2\n",
      "Positional arguments:  (3, 6)\n",
      "Keyword arguments:  {}\n",
      "Result:  9\n",
      "未交换顺序前：\n",
      "Running function:  new_function\n",
      "Positional arguments:  (2, 7)\n",
      "Keyword arguments:  {}\n",
      "Result:  81\n",
      "交换顺序后：\n",
      "Running function:  add_ints4\n",
      "Positional arguments:  (2, 7)\n",
      "Keyword arguments:  {}\n",
      "Result:  9\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "81"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 装饰器: 把一个函数作为输入且返回另外一个函数\n",
    "# 需使用如下python技巧\n",
    "# 1. *args和**kwargs\n",
    "# 2. 闭包\n",
    "# 3. 作为参数的函数\n",
    "def document_it(func):\n",
    "    def new_function(*args, **kwargs):\n",
    "        print('Running function: ', func.__name__)\n",
    "        print('Positional arguments: ', args)\n",
    "        print('Keyword arguments: ', kwargs)\n",
    "        result = func(*args, **kwargs)\n",
    "        print('Result: ', result)\n",
    "        return result\n",
    "    return new_function\n",
    "\n",
    "# 人工赋值\n",
    "def add_ints(a, b):\n",
    "    return a + b\n",
    "\n",
    "cooler_add_ints = document_it(add_ints)\n",
    "cooler_add_ints(3, 5)\n",
    "\n",
    "# 在函数定义时添加\n",
    "@document_it\n",
    "def add_ints2(a, b):\n",
    "    return a + b\n",
    "\n",
    "add_ints2(3, 6)\n",
    "\n",
    "# 可添加多个装饰器，且任何顺序都会得到相同的最终结果。中间步骤的实现还是有不一样的。\n",
    "def square_it(func):\n",
    "    def new_function(*args, **kwargs):\n",
    "        result = func(*args, **kwargs)\n",
    "        return result * result\n",
    "    return new_function\n",
    "\n",
    "print(\"未交换顺序前：\")\n",
    "@document_it\n",
    "@square_it\n",
    "def add_ints3(a, b):\n",
    "    return a + b\n",
    "\n",
    "add_ints3(2, 7)\n",
    "\n",
    "\n",
    "print(\"交换顺序后：\")\n",
    "@square_it\n",
    "@document_it\n",
    "def add_ints4(a, b):\n",
    "    return a + b\n",
    "\n",
    "add_ints4(2, 7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "inside the getter\n",
      "inside the getter\n",
      "inside the setter\n",
      "inside the getter\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Daffy'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 类class\n",
    "# 使用属性property对特性attribute进行访问和设置\n",
    "class Duck():\n",
    "    def __init__(self, input_name):\n",
    "        self.hidden_name = input_name\n",
    "    def get_name(self):\n",
    "        print('inside the getter')\n",
    "        return self.hidden_name\n",
    "    def set_name(self, input_name):\n",
    "        print('inside the setter')\n",
    "        self.hidden_name = input_name\n",
    "    \n",
    "    name = property(get_name, set_name) # 这里定义属性property\n",
    "    \n",
    "fowl = Duck('Howard')\n",
    "fowl.name\n",
    "fowl.get_name()\n",
    "\n",
    "# 对 name特性赋值时，调用set_name()方法\n",
    "fowl.name = 'Daffy' # 相当于fowl.set_name('Daffy')\n",
    "fowl.name\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "inside the getter\n",
      "inside the setter\n",
      "inside the getter\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Donald'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用修饰符定义属性。 `@property`指示getter方法, `@属性名.setter`指示setter方法\n",
    "class Duck():\n",
    "    def __init__(self, input_name):\n",
    "        self.hidden_name = input_name\n",
    "        \n",
    "    @property\n",
    "    def name(self):\n",
    "        print('inside the getter')\n",
    "        return self.hidden_name\n",
    "    \n",
    "    @name.setter\n",
    "    def name(self, input_name):\n",
    "        print('inside the setter')\n",
    "        self.hidden_name = input_name\n",
    "        \n",
    "fowl = Duck('Howard')\n",
    "fowl.name\n",
    "fowl.name = 'Donald'\n",
    "fowl.name\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Howard'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 用__name代替以上hidden_name特性，python对隐藏在类内部的特性有独特的命名规范，`__特性名`，如__name\n",
    "class Duck():\n",
    "    def __init__(self, input_name):\n",
    "        self.__name = input_name\n",
    "        \n",
    "    @property\n",
    "    def name(self):\n",
    "        print('inside the getter')\n",
    "        return self.__name\n",
    "    \n",
    "    @name.setter\n",
    "    def name(self, input_name):\n",
    "        print('inside the setter')\n",
    "        self.__name = input_name\n",
    "        \n",
    "fowl = Duck('Howard')\n",
    "# 无法访问__name特性\n",
    "# fowl.__name\n",
    "# python特有的访问方法： _类名__特性名\n",
    "fowl._Duck__name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A has  0  little objects.\n",
      "create easy_a of A\n",
      "easy_a's count:  1\n",
      "------------\n",
      "create breezy_a of A\n",
      "easy_a's count:  2\n",
      "breezy_a's count:  2\n",
      "------------\n",
      "create wheezy_a of A\n",
      "easy_a's count:  3\n",
      "breezy_a's count:  3\n",
      "wheezy_a's count:  3\n",
      "------------\n",
      "A has  3  little objects.\n",
      "------------\n",
      "This CoyoteWeapon has been brought to you by Acme.\n"
     ]
    }
   ],
   "source": [
    "# 方法（函数）的类型：\n",
    "# 1. 实例方法：以self作为第一个参数。调用时把对象作为self参数传入。\n",
    "# 2. 类方法：用`@classmethod`修饰方法且以cls（即class）作为第一个参数。作用于整个类，对类作出的任何改变都会对它的所有实例对象产生影响。\n",
    "# 3. 静态方法：用`@staticmethod`修饰方法，不需要self和cls参数。即不影响类也不影响类的对象\n",
    "\n",
    "class A():\n",
    "    count = 0 # 记录有多少个类A的对象被创建\n",
    "    \n",
    "    def __init__(self):\n",
    "#         self.count += 1 # count永远为1\n",
    "        A.count += 1 # 这里用A.count，而不是self.count，与以下cls.count作用一样，作为类A的记数。注意，所有对象的count都会一起变化。\n",
    "    \n",
    "    def exclaim(self):\n",
    "        print(\"I'm an A!\")\n",
    "    \n",
    "    @classmethod\n",
    "    def kids(cls):\n",
    "        print(\"A has \", cls.count, \" little objects.\")\n",
    "\n",
    "A.kids()\n",
    "easy_a = A()\n",
    "print(\"create easy_a of A\")\n",
    "print(\"easy_a's count: \", easy_a.count)\n",
    "print(\"------------\")\n",
    "breezy_a = A()\n",
    "print(\"create breezy_a of A\")\n",
    "print(\"easy_a's count: \", easy_a.count)\n",
    "print(\"breezy_a's count: \", breezy_a.count)\n",
    "print(\"------------\")\n",
    "wheezy_a = A()\n",
    "print(\"create wheezy_a of A\")\n",
    "print(\"easy_a's count: \", easy_a.count)\n",
    "print(\"breezy_a's count: \", breezy_a.count)\n",
    "print(\"wheezy_a's count: \", wheezy_a.count)\n",
    "print(\"------------\")\n",
    "A.kids()\n",
    "\n",
    "class CoyoteWeapon():\n",
    "    @staticmethod\n",
    "    def commercial():\n",
    "        print('This CoyoteWeapon has been brought to you by Acme.')\n",
    "\n",
    "print(\"------------\")\n",
    "CoyoteWeapon.commercial()\n",
    "\n",
    "# 说明，在讨论python类的时候，有几个约定：\n",
    "# 1.attribute，特性（或属性，要看讨论这部分内容时具体的上下文），数据，类变量\n",
    "# 2.method，方法，函数，类函数，类方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "# 对于所有的关系型数据库，SQL是不完全相同的，且python的DB-API仅仅实现共有的那部分，每一种数据库实现的是包含自己特征和哲学的方言。\n",
    "# 而SQLAlchemy是其中一个著名的用于消除数据库之间差异的跨数据库的python库。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You\n",
      "Found  4  matches\n"
     ]
    }
   ],
   "source": [
    "# 关于正则表达式匹配\n",
    "# match/search/findall/sub\n",
    "\n",
    "import re\n",
    "source = 'Young Frankenstein'\n",
    "m = re.match('You', source)\n",
    "if m:\n",
    "    print(m.group())\n",
    "else:\n",
    "    print(\"not match\")\n",
    "    \n",
    "n = re.findall('n', source)\n",
    "print('Found ', len(n), ' matches')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Got:  5\n",
      "Got:  helloworld\n",
      "[1] Got: 5\n",
      "[2] Got: helloworld\n"
     ]
    }
   ],
   "source": [
    "# 闭包、回调\n",
    "def apply_async(func, *args, callback):\n",
    "    result = func(*args)\n",
    "    \n",
    "    callback(result)\n",
    "\n",
    "def print_result(result):\n",
    "    print('Got: ', result)\n",
    "    \n",
    "def add(x, y):\n",
    "    return x + y\n",
    "\n",
    "apply_async(add, 2, 3, callback=print_result)\n",
    "apply_async(add, 'hello', 'world', callback=print_result)\n",
    "\n",
    "def make_handler():\n",
    "    sequence = 0 # （1）\n",
    "    def handler(result): # handler就是闭包\n",
    "        nonlocal sequence # 声明此变量作用域不是在handler的范围内，是外部(1)处，即make_handler函数范围内。\n",
    "        sequence += 1\n",
    "        print('[{}] Got: {}'.format(sequence, result))\n",
    "    return handler\n",
    "\n",
    "handler = make_handler()\n",
    "apply_async(add, 2, 3, callback=handler)\n",
    "apply_async(add, 'hello', 'world', callback=handler)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----map----\n",
      "[101, 102, 104, 105, 106, 111, 122, 133]\n",
      "----map None----\n",
      "<map object at 0x11119dc50>\n",
      "----reduce----\n",
      "84\n",
      "----filter----\n",
      "[1, 5, 11, 33]\n",
      "----lambda----\n",
      "[2, 4, 8, 10, 12, 22, 44, 66]\n"
     ]
    }
   ],
   "source": [
    "# map/reduce/filter/lambda\n",
    "from functools import reduce\n",
    "\n",
    "def add(x):\n",
    "    return x + 100\n",
    "\n",
    "nums = [1, 2, 4, 5, 6, 11, 22, 33]\n",
    "\n",
    "print(\"----map----\")\n",
    "print(list(map(add, nums)))\n",
    "\n",
    "print(\"----map None----\")\n",
    "print(map(None, nums))\n",
    "\n",
    "def add2(x, y):\n",
    "    return x + y\n",
    "\n",
    "print(\"----reduce----\")\n",
    "print(reduce(add2, nums))\n",
    "\n",
    "def is_odd(n):\n",
    "    return n % 2 == 1\n",
    "\n",
    "print(\"----filter----\")\n",
    "print(list(filter(is_odd, nums)))\n",
    "\n",
    "print(\"----lambda----\")\n",
    "print(list(map(lambda x: x*2, nums)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class '__main__.CC'>\n",
      "<class '__main__.CC'>\n",
      "<class '__main__.CCN'>\n",
      "<class '__main__.CCN'>\n"
     ]
    }
   ],
   "source": [
    "# 测试验证在python3.x中，经典类写法与新式类写法都默认继承object类。\n",
    "# 即python3.x中默认都是新式类，不必显式继承object类。\n",
    "class CC: #经典类写法\n",
    "    def __init__(self):\n",
    "        pass\n",
    "\n",
    "class CCN(object): #新式类写法\n",
    "    def __init__(self):\n",
    "        pass\n",
    "    \n",
    "c1 = CC()\n",
    "c2 = CCN()\n",
    "\n",
    "# 比较实例对象的type和__class__，如果x是一个新式类的实例，那么type(x)和x.__class__是一样的结果。\n",
    "print(c1.__class__)\n",
    "print(type(c1))\n",
    "print(c2.__class__)\n",
    "print(type(c2))\n",
    "\n",
    "# **python 2.x中默认都是经典类，只有显式继承了object才是新式类。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "Missing parentheses in call to 'print' (<ipython-input-2-bc9089c2bc47>, line 6)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  File \u001b[0;32m\"<ipython-input-2-bc9089c2bc47>\"\u001b[0;36m, line \u001b[0;32m6\u001b[0m\n\u001b[0;31m    print \"enter A\"\u001b[0m\n\u001b[0m                  ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m Missing parentheses in call to 'print'\n"
     ]
    }
   ],
   "source": [
    "# 关于经典类与新式类的类继承写法及效果的差异\n",
    "\n",
    "# 经典类的继承\n",
    "class A:\n",
    "    def __init__(self):\n",
    "        print \"enter A\"\n",
    "        print \"leave A\"\n",
    "\n",
    "class B(A):\n",
    "    def __init__(self):\n",
    "        print \"enter B\"       \n",
    "        A.__init__(self)  # ** 这种是非绑定的类方法（用父类名A来调用），并在参数列表中，引入待绑定的子类B对象（self），从而达到调用父类A的目的。\n",
    "        print \"leave B\"\n",
    "    \n",
    "b = B()\n",
    "\n",
    "# 这样做的缺点是，当子类B的父类A发生变化时（如类B的父类由A变为C时），必须遍历整个类定义，把所有的通过非绑定的方法的类名全部替换过来。\n",
    "class B(C):    # A 变成 C，这里要改\n",
    "    def __init__(self):\n",
    "        print \"enter B\"\n",
    "        C.__init__(self)  # A 变成 C， 这里也要改\n",
    "        print \"leave B\"\n",
    "\n",
    "# 新式类的继承(以下写法在python2x和python3x中都可以)\n",
    "class A(object):\n",
    "    def __init__(self):\n",
    "        print \"enter A\"  # python3x中，请改成 print(\"enter A\")\n",
    "        print \"leave A\"\n",
    "\n",
    "class B(A):     # 即使B的父类由A变成C，只需要改这里。\n",
    "    def __init__(self):\n",
    "        print \"enter B\"\n",
    "        super(B, self).__init__() #这里使用了super()。\n",
    "        print \"leave B\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "enter F\n",
      "enter E\n",
      "enter B\n",
      "leave B\n",
      "enter C\n",
      "enter D\n",
      "enter A\n",
      "leave A\n",
      "leave D\n",
      "leave C\n",
      "leave E\n",
      "enter D\n",
      "enter A\n",
      "leave A\n",
      "leave D\n",
      "leave F\n"
     ]
    }
   ],
   "source": [
    "# 关于类继承的顺序MRO\n",
    "# 以下是反面例子，混合使用了非绑定的类方法和super()方法，出现了类A和类D的初始化函数被重复调用了2次的情况。\n",
    "class A(object):\n",
    "    def __init__(self):\n",
    "        print(\"enter A\")\n",
    "        print(\"leave A\")\n",
    "        \n",
    "class B(object):\n",
    "    def __init__(self):\n",
    "        print(\"enter B\")\n",
    "        print(\"leave B\")\n",
    "        \n",
    "class C(A):\n",
    "    def __init__(self):\n",
    "        print(\"enter C\")\n",
    "        super(C, self).__init__()  # 这里使用了super()方法\n",
    "        print(\"leave C\")\n",
    "        \n",
    "class D(A):\n",
    "    def __init__(self):\n",
    "        print(\"enter D\")\n",
    "        super(D, self).__init__()  # 这里使用了super()方法\n",
    "        print(\"leave D\")\n",
    "        \n",
    "class E(B, C):\n",
    "    def __init__(self):\n",
    "        print(\"enter E\")\n",
    "        B.__init__(self)  # 这里使用了非绑定的类方法\n",
    "        C.__init__(self)  # 这里使用了非绑定的类方法\n",
    "        print(\"leave E\")\n",
    "        \n",
    "class F(E, D):\n",
    "    def __init__(self):\n",
    "        print(\"enter F\")\n",
    "        E.__init__(self)  # 这里使用了非绑定的类方法\n",
    "        D.__init__(self)  # 这里使用了非绑定的类方法\n",
    "        print(\"leave F\")\n",
    "        \n",
    "f = F()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "enter F\n",
      "enter E\n",
      "enter B\n",
      "enter C\n",
      "enter D\n",
      "enter A\n",
      "leave A\n",
      "leave D\n",
      "leave C\n",
      "leave B\n",
      "leave E\n",
      "leave F\n",
      "(<class '__main__.F'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>)\n"
     ]
    }
   ],
   "source": [
    "# 只使用super()方法\n",
    "class A(object):\n",
    "    def __init__(self):\n",
    "        print(\"enter A\")\n",
    "        super(A, self).__init__()  # 增加super()\n",
    "        print(\"leave A\")\n",
    "        \n",
    "class B(object):\n",
    "    def __init__(self):\n",
    "        print(\"enter B\")\n",
    "        super(B, self).__init__()  # 增加super()\n",
    "        print(\"leave B\")\n",
    "        \n",
    "class C(A):\n",
    "    def __init__(self):\n",
    "        print(\"enter C\")\n",
    "        super(C, self).__init__()  # 不变\n",
    "        print(\"leave C\")\n",
    "        \n",
    "class D(A):\n",
    "    def __init__(self):\n",
    "        print(\"enter D\")\n",
    "        super(D, self).__init__()  # 不变\n",
    "        print(\"leave D\")\n",
    "        \n",
    "class E(B, C):\n",
    "    def __init__(self):\n",
    "        print(\"enter E\")\n",
    "        super(E, self).__init__()  # 这里删掉反例中使用的非绑定的类方法 `B.__init__(self)` 和`C.__init__(self)`改成super()方法\n",
    "        print(\"leave E\")\n",
    "        \n",
    "class F(E, D):\n",
    "    def __init__(self):\n",
    "        print(\"enter F\")\n",
    "        super(F, self).__init__()  # 这里删掉反例中使用的非绑定的类方法 `E.__init__(self)` 和`D.__init__(self)`改成super()方法\n",
    "        print(\"leave F\")\n",
    "        \n",
    "f = F()\n",
    "print(f.__class__.__mro__)\n",
    "\n",
    "# 初始化顺序为 F -> E -> B -> C -> D -> A -> object\n",
    "# MRO拓扑图\n",
    "#        object\n",
    "#       /        \\\n",
    "#     /          A\n",
    "#    |         /   \\\n",
    "#   B      C      D\n",
    "#     \\   /       /\n",
    "#      E       /\n",
    "#        \\  /\n",
    "#         F\n",
    "\n",
    "# 小结\n",
    "# 1. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用，而且保证每个父类函数只调用一次（如果每个类都使用super）；\n",
    "# 2. 混用super类和非绑定的函数是一个危险行为，这可能导致应该调用的父类函数没有调用或者一个父类函数被调用多次。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "# super()是用来解决多重继承问题的，直接用非绑定的类方法（用父类名来调用）在使用单继承的时候没问题，但是如果使用多继承，会涉及到查找顺序（MRO）、重复调用（钻石继承）等种种问题。\n",
    "# 剖析super()和MRO(Method Resolution Order)\n",
    "# python中super()的定义如下\n",
    "# def super(cls, inst):\n",
    "#     mro = inst.__class__.mro()\n",
    "#     return mro[mro.index(cls) + 1]\n",
    "# 参数 cls 和 inst 分别做了两件事： \n",
    "# 1. inst 即类对象实例，通过__class__.mro()方法生成 MRO 的列表\n",
    "# 2. 通过 cls 定位当前 MRO 中的 index, 并返回 mro[index + 1]即下一个位置的类。\n",
    "# 以上两件事就是 super() 的实质。\n",
    "# 通过以上例子`f.__class__.__mro__`可打印出mro路径。\n",
    "# 在 MRO 中，基类永远出现在派生类后面，如果有多个基类，基类的相对顺序保持不变。\n",
    "# 以上super()和MRO都是针对新式类的，如果不是新式类，只能老老实实用父类的类名去调用函数了。\n",
    "\n",
    "# 对于有参数的情况，也是类似的，写法如下\n",
    "class A(object):\n",
    "    def __init__(self, strName, *args):\n",
    "        self.name = strName\n",
    "        super(A, self).__init__(*args)\n",
    "            \n",
    "class B(object):\n",
    "    def __init__(self, id):\n",
    "        self.id = id\n",
    "        \n",
    "class C(A, B):\n",
    "    def __init__(self, *args):\n",
    "        super(C, self).__init__(*args)\n",
    "\n",
    "\n",
    "#  另外，如果没有复杂的继承结构，super 作用不大。而复杂的继承结构本身就是不良设计。对于多重继承的用法，现在比较推崇 Mixin 的方式，也就是\n",
    "# 1. 普通类多重继承只能有一个普通父类和若干个 Mixin 类（保持主干单一）\n",
    "# 2.Mixin 类不能继承普通类（避免钻石继承）\n",
    "# 3.Mixin 类应该单一职责\n",
    "# 如果按照上述标准，只使用 Mixin 形式的多继承，那么不会有钻石继承带来的重复方法调用，也不会有复杂的查找顺序 ，此时super()是可有可无的，用不用全看个人喜好。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "new and cls:  <class '__main__.A'>\n",
      "init and self:  <__main__.A object at 0x00000000045850B8>\n",
      "---------------\n",
      "call and self:  <__main__.A object at 0x00000000045850B8>\n"
     ]
    }
   ],
   "source": [
    "# 关于__new__, __init__, __call__\n",
    "# 1.__new__(cls, *args, **kwargs)  创建对象时调用，返回当前对象的一个实例，这里的第一个参数是cls即class本身，是类级别的。\n",
    "# 2.__init__(self, *args, **kwargs)  在创建完对象后调用，对当前对象实例的一些初始化，无返回值，即在调用__new__之后，根据返回的实例初始化，这里的第一个参数是self即对象本身\n",
    "# 3.__call__(self,  *args, **kwargs) 如果类实现了这个方法，相当于把这个类的对象当作函数来使用，相当于 重载了括号运算符。\n",
    "class A(object):\n",
    "    def __init__(self, *args, **kwargs):\n",
    "        print(\"init and self: \", self)\n",
    "        super(A, self).__init__(*args, **kwargs)\n",
    "    def __new__(cls, *args, **kwargs):\n",
    "        print(\"new and cls: \", cls)\n",
    "        return super(A, cls).__new__(cls, *args, **kwargs)\n",
    "    def __call__(self,  *args, **kwargs):\n",
    "        print(\"call and self: \", self)\n",
    "        \n",
    "aa = A()\n",
    "print(\"---------------\")\n",
    "aa()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
